import { AlgengineApi } from '@/api/vmiot/algengine'
import { MonitorDeviceApi } from '@/api/vmiot/monitordevice'
import { PhysicalSensorApi } from '@/api/vmiot/physicalsensor'
import { TaskApi } from '@/api/vmiot/task'
import { defineStore } from 'pinia'

export const useTaskStore = defineStore('task', {
  state: () => ({
    sensorList: <any[]>[],
    sauTemplateList: <any[]>[],
    computeNodeList: <any[]>[],
    monitorDeviceList: <any[]>[],
    taskData: <any>{
      name: '',
      monitorDeviceId: '',
      content: { nodes: [], edges: [] },
      state: 1
    },
    sauInstanceMap: new Map<string, any>(),
    isInit: false
  }),
  actions: {
    async getMonitorDeviceList() {
      const deviceRes = await MonitorDeviceApi.getAllMonitorDeviceList()
      this.monitorDeviceList = deviceRes
    },

    async getSensorList() {
      const sensorRes = await PhysicalSensorApi.getPhysicalSensorPage({
        pageNo: 1,
        pageSize: 100
      })
      this.sensorList = sensorRes.list
    },

    async getSauTemplateList() {
      const sauTemplateRes = await AlgengineApi.getSauTemplate({
        pageNum: 1,
        pageSize: 10
      })
      this.sauTemplateList = sauTemplateRes.list
    },

    async getDetail(id) {
      if (!id) {
        return
      }
      const res = await TaskApi.getTask(id)
      if (res.content) {
        res.content = JSON.parse(res.content)
      }
      this.taskData = res
      console.log(this.taskData)
    },

    async initSauInstance() {
      // 批量获取 sau 实例并等待所有请求完成后再设置 isInit
      if (this.taskData && this.taskData.content.nodes) {
        const promises = this.taskData.content.nodes
          .filter((node) => node.type === 'default' && node.data.sauInstanceId)
          .map(async (node) => {
            try {
              const res = await AlgengineApi.getSauDetail({
                sauInstanceId: node.data.sauInstanceId
              })
              this.sauInstanceMap.set(node.data.sauInstanceId, res)
            } catch (error) {
              // 请求失败时，也把错误存到 sauInstanceMap
              this.sauInstanceMap.delete(node.data.sauInstanceId)
              // this.sauInstanceMap.set(node.data.sauInstanceId, error)
            }
          })

        try {
          await Promise.all(promises)
        } catch (error) {
        } finally {
          this.isInit = true
        }
      } else {
        this.isInit = true
      }
    },

    async init(id) {
      this.isInit = false
      this.sauInstanceMap.clear()
      this.getMonitorDeviceList()
      this.getSensorList()
      await this.getSauTemplateList()
      await this.getDetail(id)
      this.initSauInstance()

      // 计算节点
      const computeNodeRes = await AlgengineApi.getComputeNodeList({
        pageNum: 1,
        pageSize: 10
      })

      this.computeNodeList = computeNodeRes.list
    },

    getSensor(id: number) {
      return this.sensorList.find((item) => item.id === id)
    },

    getSensorBySensorId(sensorId: string) {
      return this.sensorList.find((item) => item.sensorId === sensorId)
    },

    getSauTemplate(sauTemplateId: string) {
      return this.sauTemplateList.find((item) => item.sauTemplateId === sauTemplateId)
    },

    getSensorOutputSignalType(sensorId: string) {
      const sensor = this.sensorList.find((item) => item.sensorId === sensorId)
      return sensor?.outputSignalType || ''
    },

    getTemplateInputSignalType(sauTemplateId: string) {
      const template = this.sauTemplateList.find((item) => item.sauTemplateId === sauTemplateId)
      return template?.inputSignalType || []
    },
    /**
     * 判断是否匹配信号类型
     * @param sauTemplateId sau配置模版id
     * @param sensorId 物理传感器id
     * @returns
     */
    isMatchSignalType(sauTemplateId, sensorId) {
      return this.getTemplateInputSignalType(sauTemplateId).includes(
        this.getSensorOutputSignalType(sensorId)
      )
    },

    /**
     * 判断已经存在的sau实例中是否包含物理传感器
     * @param sauInstanceId sau实例id
     * @param sensorId 物理传感器id
     * @returns
     */
    isExistSensorInSauInstance(sauInstanceId, sensorId) {
      const sauInstance = this.sauInstanceMap.get(sauInstanceId)
      if (sauInstance) {
        return sauInstance.physicalSensorList.flat().includes(sensorId)
      } else {
        return false
      }
    },

    // 生成按类型分组的键值对象数据
    generateSensorColumnRecord(sauTemplateId: string) {
      const columns: Record<string, any> = {}
      const signalTypes = this.getTemplateInputSignalType(sauTemplateId)
      signalTypes.forEach((type, index) => {
        columns[index] = {
          type: type,
          list: []
        }
      })
      return columns
    },

    // 将二维数组数据转换为按类型分组的键值对象数据
    setSensorColumnRecordData(sensorColumnRecord, physicalSensorList: any[][]) {
      for (const row of physicalSensorList) {
        row.forEach((item, colIndex) => {
          if (sensorColumnRecord[colIndex]) {
            sensorColumnRecord[colIndex].list.push(item)
          }
        })
      }
    },

    /**
     * 将物理传感器数据添加到指定类型的分组中
     * @param sensorColumnRecord
     * @param sensorData
     * @returns
     */
    addNewSensor(sensorColumnRecord, sensorData) {
      for (const key in sensorColumnRecord) {
        if (sensorColumnRecord[key].type === sensorData.sensorObj.outputSignalType) {
          sensorColumnRecord[key].list.push(sensorData.sensorObj.sensorId)
          return
        }
      }
    },

    /**
     * 将Record<Record<string, { list: any[],type: string }>>数据转为二维数组数据
     * @param data
     * @returns
     */
    transposeLists(data: Record<string, { list: any[] }>): any[][] {
      // 1. 提取所有 list
      const lists = Object.values(data).map((item) => item.list)

      // 2. 取最大长度
      const maxLength = Math.max(...lists.map((list) => list.length))

      // 3. 生成结果
      const result: any[][] = []
      for (let i = 0; i < maxLength; i++) {
        //只取sensorId
        const row = lists.map((list) => (list[i] !== undefined ? list[i] : ''))
        result.push(row)
      }
      return result
    },

    /**
     * 判断二维数组是否存在空值
     * @param matrix 二维数组数据
     * @returns
     */
    hasEmptySensor(matrix: any[][]): boolean {
      return matrix.some((row) => row.some((cell) => cell === ''))
    }
  }
})
